/*
 * Copyright 2017 Baiyyy
 * @(#)SuplReportIstrHdl.java
 */

package com.byyy.ccts.modules.cc.handle.istr.v23;

import com.byyy.ccts.modules.cc.Global;
import com.byyy.ccts.core.utils.DateUtils;
import com.byyy.ccts.core.utils.HexUtils;
import com.byyy.ccts.core.utils.InstructionUtils;
import com.byyy.ccts.modules.cc.entity.ccts.TSHumiture;
import com.byyy.ccts.modules.cc.entity.istr.InstructionMdl;
import com.byyy.ccts.modules.cc.entity.istr.SuplData;
import com.byyy.ccts.modules.cc.entity.istr.ext.BaseStationData;
import com.byyy.ccts.modules.cc.entity.istr.ext.WarningThresholdData;
import com.byyy.ccts.modules.cc.entity.istr.v23.DSuplReportMdl;
import com.byyy.ccts.modules.cc.handle.istr.IHandler;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

/**
 * 178A协议V2.3 补传数据上报指令处理类
 * Created by DELL on 2018-4-27.
 */
@Service("dSuplReportIstrHdl")
public class DSuplReportIstrHdl extends IHandler {

    /**
     * 补传数据上报指令处理
     * 1.校验(已提出共通)
     * 2.解析登录指令
     * 3.将数据插入数据库
     * 4.应答(已提出共通)
     * @param instructions
     * @return
     */
    @Override
    public byte[] handle(byte[] instructions) {
        logger.debug("补传数据V2.3 开始执行");
        // 解析登录指令
        InstructionMdl istrMdl = this.generateInstructionModel(instructions);
        DSuplReportMdl suplReportMdl = new DSuplReportMdl();
        suplReportMdl.setDeviceId(istrMdl.getDeviceId());
        suplReportMdl.setSequenceNum(istrMdl.getSequenceNum());

        // 补传数据条数（N）
        int count = instructions[15];
        // 每条补传数据的偏移量
        int offset = 0;
        int lenPerData = 0;
        byte[] perData = null;
        List<SuplData> suplDatas = new ArrayList(count);

        // 循环遍历生成补传数据
        for (int i = 0; i < count; i++) {
            // 获取每条补传数据的长度
            lenPerData = HexUtils.bytes2int(new byte[]{
                    // 高位补0
                    0x00, 0x00,
                    instructions[16 + offset],
                    instructions[17 + offset]
            });
            // 生成补传数据字节数组
            perData = new byte[lenPerData + 2];
            for (int j = 0; j < perData.length; j++) {
                perData[j] = instructions[16 + offset + j];
            }

            // 处理每条补传数据
            suplDatas.add(parsePerData(perData));
            // 处理完每条数据之后增加偏移量
            offset += lenPerData + 2;
        }
        suplReportMdl.setSuplDatas(suplDatas);

        this.insert(suplReportMdl);

        logger.debug("补传数据V2.3 执行结束");
        // 生成应答信息，返回
        return InstructionUtils.generateCommResponse(suplReportMdl, Global.ISTR_D_SUPPLEMENT_REPORT);
    }

    /**
     * 解析每条补传数据
     * @param perData
     * @return
     */
    private SuplData parsePerData(byte[] perData) {
        SuplData suplData = new SuplData();

        // 补传数据长度
        suplData.setLen(HexUtils.bytes2int(new byte[]{
                // 高位补0
                0x00, 0x00,
                perData[0],
                perData[1]
        }));
        // GSM时间 ---年
        suplData.setGsmYear(perData[2]);
        // GSM时间 ---月
        suplData.setGsmMonth(perData[3]);
        // GSM时间 ---日
        suplData.setGsmDay(perData[4]);
        // GSM时间 ---时
        suplData.setGsmHour(perData[5]);
        // GSM时间 ---分
        suplData.setGsmMinute(perData[6]);
        // GSM时间 ---秒
        suplData.setGsmSecond(perData[7]);
        // 信号量
        suplData.setSemaphore(perData[8]);
        // 电池电量
        suplData.setElectric(perData[9]);
        // 内部温度符号
        suplData.setTempSymbol(perData[10]);
        // 内部温度值整数
        suplData.setTempeInt(perData[11]);
        // 内部温度值小数
        suplData.setTempDec(perData[12]);
        // 环境温度符号
        suplData.setEnvTempSymbol(perData[13]);
        // 环境温度值整数
        suplData.setEnvTempeInt(perData[14]);
        // 环境温度值小数
        suplData.setEnvTempeDec(perData[15]);
        // 湿度值
        suplData.setHumidity(perData[16]);
        // 报警标志状态
        suplData.setWarnState(new byte[]{
                perData[17],
                perData[18],
                perData[19],
                perData[20]
        });

        // 扩展信息-(循环取报警阈值, 基站信息,光感量信息)
        int extOffset = 0;
        int perExtLen = 0;
        byte[] extInfo = null;
        for (int i = 0; i < 3; i++) {
            // 判断接下来的是否为扩展信息(扩展信息起始位置(21) + 偏移量 + 校验位(1) + 包尾(1) >= 数组长度)
            if ((23 + extOffset) >= perData.length) {
                break;
            }
            // 获取每条信息长度，用作偏移量
            perExtLen = perData[22 + extOffset];
            // 重组数组
            extInfo = new byte[perExtLen + 2];
            for (int j = 0; j < extInfo.length; j++) {
                extInfo[j] = perData[21 + extOffset + j];
            }
            // 将解析结果保存到DRealTimeReportMdl
            parseExtInfo(extInfo, suplData);
            // 偏移量 += 每条信息长度 + 1(扩展信息ID长度) + 1(扩展信息长度的长度)
            extOffset += perExtLen + 2;
        }

        return suplData;
    }

    /**
     * 解析扩展信息
     * @param extInfo
     * @param suplData
     */
    public void parseExtInfo(byte[] extInfo, SuplData suplData) {
        switch (extInfo[0]) {
            case Global.EXT_0X01 :
                suplData.setExtInfo1Id(extInfo[0]);
                suplData.setExtInfo1Lenth(extInfo[1]);
                WarningThresholdData extInfo1 = new WarningThresholdData();
                extInfo1.setTempSymbolH(extInfo[2]);
                extInfo1.setTempIntH(extInfo[3]);
                extInfo1.setTempDecH(extInfo[4]);
                extInfo1.setTempSymbolL(extInfo[5]);
                extInfo1.setTempIntL(extInfo[6]);
                extInfo1.setTempDecL(extInfo[7]);
                extInfo1.setHumidityH(extInfo[8]);
                extInfo1.setHumidityL(extInfo[9]);
                extInfo1.setElectricL(extInfo[10]);
                suplData.setWarningThresholdData(extInfo1);
                break;
            case Global.EXT_0X02 :
                suplData.setExtInfo2Id(extInfo[0]);
                suplData.setExtInfo2Lenth(extInfo[1]);
                int len = ((int) extInfo[1]) / 12;
                BaseStationData baseStationData = null;
                List<BaseStationData> baseStationDataList = new ArrayList<>();
                for (int i = 0; i < len; i++) {
                    baseStationData = new BaseStationData();
                    baseStationData.setRxl(extInfo[2 + (i * 12)]);
                    baseStationData.setMcc(new byte[]{
                            extInfo[3 + (i * 12)],
                            extInfo[4 + (i * 12)]
                    });
                    baseStationData.setMnc(extInfo[5 + (i * 12)]);
                    baseStationData.setCellid(new byte[]{
                            extInfo[6 + (i * 12)],
                            extInfo[7 + (i * 12)],
                            extInfo[8 + (i * 12)],
                            extInfo[9 + (i * 12)]
                    });
                    baseStationData.setLac(new byte[]{
                            extInfo[10 + (i * 12)],
                            extInfo[11 + (i * 12)],
                            extInfo[12 + (i * 12)],
                            extInfo[13 + (i * 12)]
                    });
                    baseStationDataList.add(baseStationData);
                }
                suplData.setBaseStationData(baseStationDataList);
                break;
            case Global.EXT_0X03 :
                suplData.setExtInfo3Id(extInfo[0]);
                suplData.setExtInfo3Lenth(extInfo[1]);
                suplData.setLightPerceptionData(new byte[]{
                        extInfo[2],
                        extInfo[3],
                        extInfo[4],
                        extInfo[5]
                });
                break;
        }
    }

    /**
     *  将实时数据插入数据库中
     */
    private void insert(DSuplReportMdl model) {
        TSHumiture tsHumiture = null;
        List<TSHumiture> tsHumitures = new ArrayList<>();
        float temperature = 0;
        for (SuplData temp : model.getSuplDatas()) {
            tsHumiture = new TSHumiture();
            tsHumiture.setDeviceSn(HexUtils.bytesToHexFun3(model.getDeviceId()));
            tsHumiture.setCollectTime(new Timestamp(DateUtils.structure(
                    temp.getGsmYear(), temp.getGsmMonth() - 1,
                    temp.getGsmDay(), temp.getGsmHour(),
                    temp.getGsmMinute(), temp.getGsmSecond()).getTime()));

            // 设置温度值,注意零下的情况
            temperature = Float.valueOf((int) temp.getTempeInt() + "." + (int) temp.getTempDec());
            if (!(Global.OTH_TEMP_SYMBOL_PLUS == temp.getTempSymbol())) {
                temperature = -temperature;
            }
            tsHumiture.setTemperature(temperature);
            tsHumiture.setSemaphore(temp.getSemaphore());
            tsHumiture.setElectric(temp.getElectric());
            tsHumiture.setHumidity(temp.getHumidity());
//            tsHumiture.setCellId(HexUtils.bytes2int(temp.getBaseStationData().get(0).getCellid()));
//            tsHumiture.setLac(HexUtils.bytes2int(temp.getBaseStationData().get(0).getLac()));
            tsHumitures.add(tsHumiture);
        }

        // 去重
        List<TSHumiture> noRepeatData = this.clearRepeatData(tsHumiture.getDeviceSn(), tsHumitures);
        if (noRepeatData == null || noRepeatData.size() < 1) {
            return;
        }

        this.insertHumiture(noRepeatData);
    }

}
